"use strict";

const path = require("path");
const Package = require("@test-cli/package");
const log = require("@test-cli/log");
const { exec: spawn } = require("@test-cli/utils");

const SETTING = {
  init: {
    name: "@test-cli/init",
    version: "1.0.7"
  }
};

const CACHE_DIR = "dependencies"; // 缓存路径

async function exec() {
  // 1.targetPath -> modulePath(commands/*)
  // 2.modulePth  -> Package(npm模块)
  // 3.Package.getRootFile(获取入口文件)
  // 4.Package.update / Package.install

  let targetPath = process.env.CLI_TARGET_PATH;
  const homePath = process.env.CLI_HOME_PATH;
  let storeDir = "";
  let pkg;

  const cmdObj = arguments[arguments.length - 1];
  const cmdName = cmdObj.name();
  const currentPackage = SETTING[cmdName];
  const packageName = currentPackage.name;
  const packageVersion = currentPackage.version;

  if (!targetPath) {
    targetPath = path.resolve(homePath, CACHE_DIR); // 生成缓存路径
    storeDir = path.resolve(targetPath, "node_modules");
    log.verbose("targetPath", targetPath);
    log.verbose("storeDir", storeDir);

    pkg = new Package({
      targetPath,
      packageName,
      packageVersion,
      storeDir
    });

    if (await pkg.exits()) {
      // 更新
      await pkg.update();
    } else {
      // 安装
      await pkg.install();
    }
  } else {
    pkg = new Package({
      targetPath,
      packageName,
      packageVersion
    });
  }

  log.verbose(`command "${cmdName}" package`, pkg);

  const rootFile = pkg.getRootFilePath();

  log.verbose(`command "${cmdName}" rootFile`, rootFile);

  if (rootFile) {
    try {
      const args = Array.from(arguments);
      const cmd = args[args.length - 1];
      // const o = {}; // 继承了Object对象
      const o = Object.create(null); // 纯粹的空对象
      Object.keys(cmd).forEach(key => {
        if (
          cmd.hasOwnProperty(key) &&
          !key.startsWith("_") &&
          key !== "parent"
        ) {
          o[key] = cmd[key];
        }
      });

      args[args.length - 1] = o;

      // 新开一个进程去执行命令
      const code = `require("${rootFile}").call(null, ${JSON.stringify(args)})`;
      const child = spawn("node", ["-e", code], {
        cwd: process.cwd(),
        stdio: "inherit"
      });

      child.on("error", e => {
        log.error(e.message);
        process.exit(1);
      });
      child.on("exit", e => {
        log.verbose("命令执行成功", e);
        process.exit(e);
      });
    } catch (e) {
      log.error(e.message);
    }
  }
}

module.exports = exec;
